package com.service;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Properties;
import java.util.zip.GZIPInputStream;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.job.Job;
import org.pentaho.di.job.JobMeta;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import com.bean.HistoryLog;
import com.bean.ImportedFile;
import com.dao.ConfigDAO;
import com.dao.HistoryLogDAO;
import com.dao.ImportedFileDAO;

public class FileService {
	
	private final static String Kettle_Viriable_CSV = "csvFile";
	private final static String Kettle_Viriable_LOG = "logPath";
	
	private static Logger logger = Logger.getLogger(FileService.class);
	
	
	private static String SOURCE_PATH = "";
	private static String TEMP_PATH = "";
	
	//private final static String Kettle_Transformation_File = "HOSPITAL_LOG.ktr";
	private static String Kettle_Job_File = "";
	private static String Kettle_Log_Path = "";
	
	static {
		Properties props = new Properties();
		try {
			props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("Setting.properties"));
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			e.printStackTrace();
		}
		
		SOURCE_PATH = props.get("SOURCE_PATH").toString();
		TEMP_PATH = props.get("TEMP_PATH").toString();
		Kettle_Job_File = props.get("Kettle_Job_File").toString();
		Kettle_Log_Path = props.get("Kettle_Log_Path").toString();
	}
	
	private ConfigDAO configDAO;
	
	private ImportedFileDAO importedFileDAO;
	
	private HistoryLogDAO historyLogDAO;
	
	
//	private final static String 
	
	public void execute() {
		
		logger.info("start to import datas");
		
		File folder = new File(SOURCE_PATH);
		
		if (folder != null && folder.isDirectory()) {
			String[] gzFileNames = folder.list(new FilenameFilter(){

				public boolean accept(File folder, String fileName) {
					if (fileName.endsWith(".gz")) {
						if (importedFileDAO == null) {
							return true;
						} else {
							return !importedFileDAO.isImported(fileName, ImportedFile.FileType_GZ);
						}
					}
					
					return false;
				}
				
			});
			
			for (String gzFileName : gzFileNames) {
				try {
					File csvFile = unzip(new File(folder, gzFileName));
					if (csvFile != null) {//not null
						if (this.importData(csvFile)) {
							ImportedFile importedFile = new ImportedFile();
							importedFile.setImportedDate(new Timestamp(new Date().getTime()));
							importedFile.setFileType(ImportedFile.FileType_GZ);
							importedFile.setName(gzFileName);
							importedFileDAO.save(importedFile);
						}
						
						//csvFile.delete();
					}
				} catch (FileNotFoundException e) {
					logger.error(e.getMessage(), e);
					e.printStackTrace();
				} catch (IOException e) {
					logger.error(e.getMessage(), e);
					e.printStackTrace();
				}
			}
			
		} else {
			logger.error(SOURCE_PATH + " does not exist or is not a folder!");
			return;
		}
		
		logger.info("finish import datas");
	}
	
	/**
	 * unzip gz file
	 * @param file
	 * @return unziped file
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private File unzip(File file) throws FileNotFoundException, IOException {
		GZIPInputStream gzi = new GZIPInputStream(new FileInputStream(file));
		int to = file.getName().lastIndexOf('.'); 
        if (to == -1) { 
            System.out.println("usage:  java expandgz  filename.gz"); 
            return null;
            //System.exit(0); 
        } 
        String fout = file.getName().substring(0, to);
        File target = new File(TEMP_PATH, fout);
        if (!target.exists()) {
        	target.createNewFile();
        }
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(target)); 

        //System.out.println("writing " + fout);

        int b; 
        do { 
            b = gzi.read(); 
            if (b==-1) break; 
            bos.write(b); 
        } while (true); 
        gzi.close();
        bos.close(); 
        
        return target;
	}
	
	private boolean importData(File csvFile) {
		//executeTrans(Kettle_Transformation_File, Kettle_Viriable_CSV, csvFile.getAbsolutePath());
		return executeJob(Kettle_Job_File, new String[]{Kettle_Viriable_CSV, Kettle_Viriable_LOG}, new String[]{csvFile.getAbsolutePath(), Kettle_Log_Path});
	}
	
	
	/**
	 * 调用作业文件
	 * @param jobName
	 * @param variableName
	 * @param variableValue
	 */
	protected boolean executeJob(String jobName, String[] variableNames, String[] variableValues) {
		
		if (StringUtils.isEmpty(jobName)) {
			logger.error("job file name cannot be empty");
			return false;
		}
		
		try {
			KettleEnvironment.init();
			
			URL url = Thread.currentThread().getContextClassLoader().getResource(jobName);
			if (url == null) {
				logger.error("cannot find job file " + jobName);
				return false;
			}
			
			JobMeta jobMeta = new JobMeta(url.getFile(), null);
		    Job job = new Job(null, jobMeta);
		  //向Job 脚本传递参数，脚本中获取参数值：${参数名}
		    for (int i=0; i<variableNames.length; i++) {
		    	job.setVariable(variableNames[i], variableValues[i]);
		    }
		    
		    job.start();
		    job.waitUntilFinished();
		    if (job.getErrors() > 0) {
		    	logger.error("errors with job file " + jobName);
		    	return false;
		    }
		    
		    return true;
		} catch (KettleException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			return false;
		}
	}
	
	/**
	 * 调用转换文件
	 * @param filename
	 * @param variableName
	 * @param variableValue
	 */
	protected void executeTrans(String filename, String variableName, String variableValue) {
		
		if (StringUtils.isEmpty(filename)) {
			logger.error("file name cannot be empty");
			return;
		}
		
		if (StringUtils.isEmpty(variableName)) {
			logger.error("variable name cannot be empty");
			return;
		}

		URL url = Thread.currentThread().getContextClassLoader().getResource(filename);
		if (url == null) {
			logger.error("cannot find trans file " + filename);
			return;
		}
		
	    try {
			KettleEnvironment.init();
			TransMeta transMeta = new TransMeta(url.getFile());
		    Trans trans = new Trans(transMeta);
		    trans.setVariable(variableName, variableValue);
		    trans.prepareExecution(null);
		    trans.startThreads();
		    trans.waitUntilFinished();
		   
		    if (trans.getErrors()!=0) {
		    	logger.error("errors with trans file " + filename);
		    }
	    } catch (KettleException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(e.getMessage(), e);
		}
	    
	}
	
	public void print() {
//		System.out.println(historyLogDAO.count(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null));
//		
//		for (Object[] log : historyLogDAO.find(HistoryLogDAO.Date_op_on, "2011-12-31", HistoryLogDAO.Date_op_withinLast_Unit_Weeks, null, "not like", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null)) {
//			System.out.println(log[0] + " " + log[1] + " " + log[2]);
//		}
	}

	public void setConfigDAO(ConfigDAO configDAO) {
		this.configDAO = configDAO;
	}
	
	public void setImportedFileDAO(ImportedFileDAO importedFileDAO) {
		this.importedFileDAO = importedFileDAO;
	}
	
	public void setHistoryLogDAO(HistoryLogDAO historyLogDAO) {
		this.historyLogDAO = historyLogDAO;
	}

	public static void main(String[] a) {
//		FileService service = new FileService();
//		service.importData();
//		SimpleDateFormat df = new SimpleDateFormat("'E' yyyy/MM/dd HH:mm:ss");
//		try {
//			System.out.println(df.parse("2 2011/12/27 03:34:37"));
//		} catch (ParseException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
//		Pattern p = Pattern.compile("\\d{4}\\/\\d{2}\\/\\d{2} \\d{2}\\:\\d{2}\\:\\d{2}");
//		Matcher matcher = p.matcher("2011/12/27 03:34:37");
//		System.out.println(matcher.find());
		
		ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{"F:/workspace/LogProject/src/applicationContext.xml"});
		FileService fileService = (FileService)ctx.getBean("fileService");
		fileService.print();
	}
}
